package com.oig.sys.auth.service.impl;

import com.oig.common.exception.BadRequestException;
import com.oig.sys.auth.dao.ITbRoleDao;
import com.oig.sys.auth.dao.ITbUserRoleDao;
import com.oig.sys.auth.dto.RoleDto;
import com.oig.sys.auth.entity.TbUser;
import com.oig.sys.auth.entity.TbUserRole;
import com.oig.sys.auth.service.ITbRolePermissionService;
import com.oig.sys.auth.service.ITbRoleResourceService;
import com.oig.sys.auth.service.ITbRoleSystemService;
import com.oig.sys.auth.service.ITbUserRoleService;
import com.oig.sys.auth.vo.PermissionVo;
import com.oig.sys.auth.vo.ResourceVo;
import com.oig.sys.auth.vo.RoleVo;
import com.oig.sys.auth.vo.SystemVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author wuxl
 */
@Service
public class TbUserRoleServiceImpl implements ITbUserRoleService {

	private final ITbUserRoleDao tbUserRoleDao;
	private final ITbRoleDao roleDao;
	private final ITbRoleSystemService roleSystemService;
	private final ITbRolePermissionService rolePermissionService;
	private final ITbRoleResourceService roleResourceService;

	@Autowired
	public TbUserRoleServiceImpl(ITbUserRoleDao tbUserRoleDao,
								 ITbRoleDao roleDao,
								 ITbRoleSystemService roleSystemService,
								 ITbRolePermissionService rolePermissionService,
								 ITbRoleResourceService roleResourceService){
		 this.tbUserRoleDao = tbUserRoleDao;
		 this.roleDao = roleDao;
		 this.roleSystemService = roleSystemService;
		 this.rolePermissionService = rolePermissionService;
		 this.roleResourceService = roleResourceService;
	}


	@Override
	public List<SystemVo> findAllOkSystemVo(Integer userId) {
		List<Integer> roleIdList=tbUserRoleDao.findByUserId(userId);
		return roleSystemService.findOkSystemByRole(roleIdList);
	}

	@Override
	public List<Integer> findAllOkSystemId(Integer userId) {
		List<Integer> roleIdList=tbUserRoleDao.findByUserId(userId);
		return roleSystemService.findOkSystemIdByRole(roleIdList);
	}

	@Override
	public List<PermissionVo> findAllOkPermissionVo(Integer userId) {
		List<Integer> roleIdList=tbUserRoleDao.findByUserId(userId);
		return this.rolePermissionService.findOkPermissionByRole(roleIdList) ;
	}


	@Override
	public List<ResourceVo> findAllOkResourceVo(Integer userId, Integer systemId) {
		List<Integer> roleIdList=tbUserRoleDao.findByUserId(userId);
		return this.roleResourceService.findOkResourceByRole(roleIdList, systemId);
	}


	@Transactional(rollbackFor = Exception.class)
	@Override
	public void delUserRoleByRoleId(Integer roleId) {
		List<Integer> roleIdList=tbUserRoleDao.findAllIdByRoleId(roleId);
		if (roleIdList!=null && !roleIdList.isEmpty()){
			this.tbUserRoleDao.deleteByIdList(roleIdList);
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void delUserRoleByUserId(Integer userId) {
		List<Integer> roleIdList=tbUserRoleDao.findAllIdByUserId(userId);
		if (roleIdList!=null && !roleIdList.isEmpty()){
			this.tbUserRoleDao.deleteByIdList(roleIdList);
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public List<RoleVo> addUserRole(TbUser user, List<RoleDto> roleDtoList) {
		List<Integer> roleIdList = roleDtoList.stream().map(RoleDto::getId).collect(Collectors.toList());
		List<RoleVo> roleVoList = this.roleDao.findAllByIdIn(roleIdList);
		Map<Integer,RoleVo> roleVoMap = roleVoList.stream().collect(Collectors.toMap(RoleVo::getId, Function.identity()));
		for (RoleDto roleDto : roleDtoList){
			if (roleDto.getId()==null){
				throw new BadRequestException("角色id为空");
			}
			RoleVo roleVo = roleVoMap.get(roleDto.getId());
			if (!roleVo.getTenantId().equals(user.getTenantId())){
				throw new BadRequestException("角色和用户不属于同一个租户") ;
			}
			TbUserRole userRole = new TbUserRole();
			userRole.setRoleId(roleDto.getId());
			userRole.setUserId(user.getId());
			this.tbUserRoleDao.save(userRole) ;
			roleIdList.add(roleDto.getId()) ;
		}
		return roleVoList ;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public List<RoleVo> updateUserRole(TbUser user, List<RoleDto> roleDtoList) {
		List<Integer> roleIdList = roleDtoList.stream().map(RoleDto::getId).collect(Collectors.toList());
		List<Integer> userRoleIdList = new ArrayList<>() ;
		List<RoleVo> roleVoList = this.roleDao.findAllByIdIn(roleIdList);
		Map<Integer,RoleVo> roleVoMap = roleVoList.stream().collect(Collectors.toMap(RoleVo::getId, Function.identity()));
		for (RoleDto roleDto : roleDtoList) {
			if (roleDto.getId()==null){
				throw new BadRequestException("角色id为空");
			}
			TbUserRole userRole = this.tbUserRoleDao.getByUserIdAndRoleId(user.getId(), roleDto.getId()) ;
			if (userRole==null){
				RoleVo roleVo = roleVoMap.get(roleDto.getId());
				if (!roleVo.getTenantId().equals(user.getTenantId())){
					throw new BadRequestException("角色和用户不属于同一个租户") ;
				}
				userRole = new TbUserRole();
				userRole.setRoleId(roleDto.getId());
				userRole.setUserId(user.getId());
				this.tbUserRoleDao.save(userRole) ;
			}
			userRoleIdList.add(userRole.getId()) ;
			roleIdList.add(roleDto.getId()) ;
		}
		List<Integer> delIdList = this.tbUserRoleDao.findAllIdByUserIdAndIdNotIN(user.getId(), userRoleIdList);
		if (delIdList!=null &&!delIdList.isEmpty()){
			this.tbUserRoleDao.deleteByIdList(delIdList);
		}
		return roleDao.findAllByIdIn(roleIdList);
	}


	@Override
	public List<Integer> getUserRoleIdList(Integer userId) {
		return this.tbUserRoleDao.findByUserId(userId);
	}

	@Override
	public List<RoleVo> getUserRole(Integer userId) {
		List<Integer> roleIdList = this.getUserRoleIdList(userId);
		return this.roleDao.findAllByIdIn(roleIdList);
	}
}
